package ckw.network;

import java.io.IOException;
import java.sql.Time;

import core.messages.*;

import ckw.database.DatabaseManager;
import ckw.database.Message;
import ckw.database.Voter;
import ckw.gui.MainWindowC;
import ckw.test.TestThread;


/**
 * 
 * @author Maks
 * W�tek odpowiedzialny za odbieranie wiadomosci od komisji i wysylanie do niej potwierdzenia
 * 
 */

public class ReceiverC implements Runnable {
	ConnectionC cm = null;
	Queue2 queue2 = null;
	StanC stanC = null;
	Komisja komisja = null;
	
	
	public ReceiverC(Komisja komisja, ConnectionC cm, Queue2 queue2, StanC stanC) {
		this.komisja = komisja;
		this.cm = cm;
		this.queue2 = queue2;
		this.stanC = stanC;
	}

	// jesli odebrano glos 
	public void odebranoGlos(VoteMsg message) throws Exception{
		DatabaseManager db = DatabaseManager.getInstance();
		int nr = 0;
		if(message != null && !db.hasMassage(komisja.getId(), message.getNumber(), message.getElectionName())){
			if(message.getVotesPackageCore() != null){
				System.out.println("Centrala otrzymala od komisji GLOS nr:msg: " + message.getNumber() + " : " + message.getMsg());
				db = DatabaseManager.getInstance();
				db.saveVotes(message.getVotesPackageCore());
				nr = 1;
			} else if(message.getSummaryPackageCore() != null) {
				
				System.out.println("Centrala otrzymala od komisji PACZKE PODSUMOWUJACA nr:msg: " + message.getNumber() + " : " + message.getMsg());
				db = DatabaseManager.getInstance();
				db.saveSummaryPackage(message.getSummaryPackageCore(), komisja.getId());
				nr = 3;
			}
			Message abba = new Message(komisja.getId(), message.getNumber(), message.getElectionName());
			db.save(abba);
		}
		// wysylamy potwierdzenie
		Ack ack = new Ack(stanC.getNr(), message.getNumber());
		ack.setInfoNr(nr);
		cm.sendDown(komisja, ack);
	}
	
	// jesli odebrano potwierdzenie 
	public void odebranoPotwierdzenie(Ack ack){
		if(ack!=null){
			System.out.println("Otrzymano potwierdzenie od komisji dla nr:msg: " + ack.getNumber() + ":" + ack.getReceived());
		} else {
			System.out.println("Nie otrzymano potwierdzenia!");
		}
	}
	
	// jesli odebrano informacje
	private void odebranoInformacje(Info info) throws Exception {
		DatabaseManager db = DatabaseManager.getInstance();
		if(info != null){
			System.out.println("Centrala otrzymala od komisji informacje nr:msg: " + info.getNumber() + " : " + info.getMsg());
		}
		switch(info.getMsg()){
		case 0:
		case 1:
		case 2:
		case 3:
		case 4:{
			// wysyla dane wyborcze do proszacej komisji
			System.out.println("Prosba o dane od komisji");
			cm.wyslijDane(komisja, info.getToken());
		}
		case 5:{
			// dostalismy info o stanie od kosmisji
			StanO stan = (StanO)info.getStan();
			if(stan!=null){
				komisja.setStan(stan);
				if (stan.isGlosowanieRozpoczete() && stan.getElectionName() != null){
					db.changeOKWElectionStatus(stan.getElectionName(), komisja.getId(), 1);
					db.checkElectionStatus(stan.getElectionName());
					MainWindowC.aktualizujWybory();
				}
				if (stan.isGlosowanieZakonczone() && stan.getElectionName() != null){
					db.changeOKWElectionStatus(stan.getElectionName(), komisja.getId(), 2);
					db.checkElectionStatus(stan.getElectionName());
					MainWindowC.aktualizujWybory();
				}
			}
			break;
		}
		}
		
		// wysylamy potwierdzenie
		Ack ack = new Ack(stanC.getNr(), info.getNumber());
		cm.sendDown(komisja, ack);
	}
	
	private void odebranoZamiejscowego(NonresidentMsg msg)  throws Exception {
		System.out.println("DANE: " + msg.getId() + " "+ msg.getElectionName());
		DatabaseManager db = DatabaseManager.getInstance();
		Voter voter = db.getNonresidentVoter(msg.getId(), msg.getElectionName());
		System.out.println("VOTER: " + voter);
		
		// cofanie
		if(msg.getHasVoted() == -1){
			if(voter!=null){
				System.out.println("COFAM");
				db.setNonresidentVoterAsVoted(voter.getIdentificationField(),msg.getElectionName(), 0, null);
				ValidationThread.removeFromList(new NonresidentValidationData(voter.getIdentificationField(), msg.getElectionName(),
						komisja.getId()));
			}	
		}
		
		// oznaczanie jako weryfikowany
		else if(msg.getHasVoted() == 1 && voter!=null 
				&& db.hasNonresidentVoterVoted(msg.getId(), msg.getElectionName())==0){
			System.out.println("USTAWIAM NA 1");
			db.setNonresidentVoterAsVoted(voter.getIdentificationField(),msg.getElectionName(), 1, komisja.getId());
			Time time = new Time(System.currentTimeMillis());
			ValidationThread.addToList(new NonresidentValidationData(voter.getIdentificationField(),
					msg.getElectionName(), komisja.getId(), time.getTime()));
			
			NonresidentMsg ansMsg = new NonresidentMsg(stanC.getNr(), voter.getIdentificationField(), 
					voter.getName(), voter.getSurname(), voter.getAddress(), msg.getElectionName());
			
			cm.sendDown(komisja, ansMsg);
		} 
		
		// potwierdzanie
		else if(msg.getHasVoted() == 2 && voter!=null && db.hasNonresidentVoterVoted(msg.getId(), msg.getElectionName())!=2){
			System.out.println("USTAWIAM NA 2");
			
			db.setNonresidentVoterAsVoted(voter.getIdentificationField(),msg.getElectionName(), 2, komisja.getId());
			ValidationThread.removeFromList(new NonresidentValidationData(voter.getIdentificationField(), msg.getElectionName(),
					komisja.getId()));

		} 
		
		
		Ack ack = new Ack(stanC.getNr(), msg.getNumber());
		cm.sendDown(komisja, ack);
	}
	

	private void odebranoWynikTestu(TestMsg msg) throws Exception {
		msg.setOkw(komisja.getId());
		TestThread.addWiadomosc(msg);
		Ack ack = new Ack(stanC.getNr(), msg.getNumber());
		cm.sendDown(komisja, ack);
	}


	public void run() {
		try{
			while(true){  
			//TODO: moze sprawdzanie czy juz nie doszla kazda wiadomosc, nie tylko glos?
				// sprawdzamy typ wiadomosci
				Object message = komisja.getOis().readObject();	
				if(message.getClass().equals(VoteMsg.class))
					odebranoGlos((VoteMsg)message);
				if(message.getClass().equals(Ack.class)){
					odebranoPotwierdzenie((Ack)message);
					queue2.findToRemove((Ack)message);
				}
				if(message.getClass().equals(Info.class))
					odebranoInformacje((Info)message);
				if(message.getClass().equals(NonresidentMsg.class))
					odebranoZamiejscowego((NonresidentMsg)message);
				if(message.getClass().equals(TestMsg.class))
					odebranoWynikTestu((TestMsg)message);
			}

		} catch (Exception e){
			e.printStackTrace();
			e.getMessage();
			try {
				if(komisja.getSocket()!=null){
					komisja.getSocket().close();
					komisja.setSocket(null);
				}
				if(komisja.getOos()!=null){
					komisja.getOos().close();
					komisja.setOos(null);
				}
				if(komisja.getOis()!=null){
					komisja.getOis().close();
					komisja.setOis(null);
				}
				if(komisja.getStan()!=null)
					komisja.getStan().setPolaczenie(false);
				System.out.println("Zamykam polaczenie...");
			} catch (IOException e1) {
				e1.printStackTrace();
			}

		}
		
		//odejmuje komisje od listy
		MainWindowC.aktualizujKomisje();
		System.out.print("Koniec odbierania od klienta");
	}


}